package cn.ctodb.app.mail;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.annotation.Resource;
import javax.mail.Address;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.stereotype.Service;

import cn.ctodb.repository.MailAccountRepository;
import cn.ctodb.security.User;
import cn.ctodb.web.rest.dto.MailDTO;
import cn.ctodb.web.rest.dto.MailDTO.address;

// 部分邮件服务器需要变更jdk的加密限制jar
//http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
@Service
public class MailService {

	@Resource
	private MailAccountRepository mailAccountRepository;

	public List<Map<String, String>> getFolds(User user) {
		MailAccount mailAccount = mailAccountRepository.findOneByUserId(user.getUserId());
		return getFolds(mailAccount);
	}

	public List<Map<String, String>> getFolds(MailAccount mailAccount) {
		List<Map<String, String>> list = new ArrayList<>();
		boolean isSSL = true;
		String host = mailAccount.getInHost();
		int port = mailAccount.getInPort();
		String username = mailAccount.getUsername();
		String password = mailAccount.getPassword();

		Properties props = new Properties();
		if ("pop3".equals(mailAccount.getProtocol())) {
			props.put("mail.store.protocol", "pop3");
			props.put("mail.pop3.ssl.enable", isSSL);
			props.put("mail.pop3.host", host);
			props.put("mail.pop3.port", port);
		} else if ("imap".equals(mailAccount.getProtocol())) {
			props.put("mail.store.protocol", "imap");
			props.put("mail.imap.ssl.enable", isSSL);
			props.put("mail.imap.host", host);
			props.put("mail.imap.port", port);
		}

		Session session = Session.getDefaultInstance(props);

		Store store = null;
		try {
			store = session.getStore(mailAccount.getProtocol());
			store.connect(username, password);
			list = _2list(store.getDefaultFolder(), list);
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
		} catch (MessagingException e) {
			e.printStackTrace();
		} finally {
			try {
				if (store != null) {
					store.close();
				}
			} catch (MessagingException e) {
				e.printStackTrace();
			}
		}
		System.out.println("接收完毕！");
		return list;
	}

	public List<MailDTO> getList(User user, String folderName) {
		return getList(mailAccountRepository.findOneByUserId(user.getUserId()), folderName, 1, 20);
	}

	public List<MailDTO> getList(MailAccount mailAccount, String folderName, int row) {
		return getList(mailAccount, folderName, 1, row);
	}

	public List<MailDTO> getList(User user, String folderName, int page, int row) {
		return getList(mailAccountRepository.findOneByUserId(user.getUserId()), folderName, page, row);
	}

	public List<MailDTO> getList(MailAccount mailAccount, String folderName, int page, int row) {
		List<MailDTO> list = new ArrayList<>();
		boolean isSSL = true;
		String host = mailAccount.getInHost();
		int port = mailAccount.getInPort();
		String username = mailAccount.getUsername();
		String password = mailAccount.getPassword();

		Properties props = new Properties();
		if ("pop3".equals(mailAccount.getProtocol())) {
			props.put("mail.store.protocol", "pop3");
			props.put("mail.pop3.ssl.enable", isSSL);
			props.put("mail.pop3.host", host);
			props.put("mail.pop3.port", port);
		} else if ("imap".equals(mailAccount.getProtocol())) {
			props.put("mail.store.protocol", "imap");
			props.put("mail.imap.ssl.enable", isSSL);
			props.put("mail.imap.host", host);
			props.put("mail.imap.port", port);
		}
		Session session = Session.getDefaultInstance(props);

		Store store = null;
		Folder folder = null;
		try {
			store = session.getStore(mailAccount.getProtocol());
			store.connect(username, password);

			folder = store.getFolder(folderName);
			folder.open(Folder.READ_ONLY);

			int size = folder.getMessageCount();
			int start = size - (page * row) + 1;
			int end = size - (page - 1) * row;
			for (int i = end; i >= start; i--) {
				if (i <= 0)
					break;
				Message message = folder.getMessage(i);
				MailDTO dto = new MailDTO();
				dto.setSubject(message.getSubject());
				dto.setContent(message.getSubject());
				dto.setFrom(new address(message.getFrom()[0]));
				dto.setDate(DateFormatUtils.format(message.getSentDate(), "hh:mm MM/dd/yyyy"));
				dto.setId(message.getSize() + "");
				list.add(dto);
				System.out.println("From:" + ArrayUtils.toString(address2string(message.getFrom())));
				System.out.println("AllRecipients:" + ArrayUtils.toString(address2string(message.getAllRecipients())));
				System.out.println("ReplyTo:" + ArrayUtils.toString(address2string(message.getReplyTo())));
				System.out.println("Subject: " + message.getSubject());
				System.out.println("Date: " + message.getSentDate());
				System.out.println("--------------------------------------------");
			}
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
		} catch (MessagingException e) {
			e.printStackTrace();
		} finally {
			try {
				if (folder != null) {
					folder.close(false);
				}
				if (store != null) {
					store.close();
				}
			} catch (MessagingException e) {
				e.printStackTrace();
			}
		}
		System.out.println("接收完毕！");
		return list;
	}

	private List<Map<String, String>> _2list(Folder folder, List<Map<String, String>> list) {
		try {
			folder.open(Folder.READ_ONLY);
			if (folder.getMessageCount() > 0) {
				Map<String, String> m = new HashMap<>();
				m.put("name",
						folderMap.containsKey(folder.getName()) ? folderMap.get(folder.getName()) : folder.getName());
				m.put("filter", System.currentTimeMillis() + "");
				m.put("filterName", folder.getFullName());
				list.add(m);
			}
		} catch (Exception e) {
		} finally {
			try {
				if (folder != null) {
					folder.close(false);
				}
			} catch (Throwable e) {
			}
		}
		try {
			for (Folder folder2 : folder.list()) {
				list = _2list(folder2, list);
			}
		} catch (MessagingException e) {
			e.printStackTrace();
		}
		return list;
	}

	private String[] address2string(Address[] addresses) {
		String[] strs = new String[addresses.length];
		for (int i = 0; i < strs.length; i++) {
			InternetAddress address = (InternetAddress) addresses[i];
			if (address.isGroup()) {
				try {
					strs[i] = ArrayUtils.toString(address2string(address.getGroup(true)));
				} catch (AddressException e) {
					e.printStackTrace();
				}
			} else {
				strs[i] = address.getPersonal() + "<" + address.getAddress() + ">";
			}
		}
		return strs;
	}

	private static final Map<String, String> folderMap = new HashMap<>();
	static {
		folderMap.put("INBOX", "收件箱");
		folderMap.put("Sent Messages", "已发送");
		folderMap.put("Junk", "已删除");
	}
}
